﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Eco.Handles;
using Eco.Services;

using Descriptions_DomainModel.Model;
using CommonClasses.Utility;
using System.IO;

namespace DomainModelEditor
{
    public partial class NodeEditForm : Form
    {
        private IUndoService undo;
        private bool result = false;

        private Node Node 
        {
            get
            {
                return NodeVH.Element.AsObject as Node;
            }

            set
            {
                NodeVH.Element.AsObject = value;
            }
        }

        public NodeEditForm(EcoSpace ecoSpace, Node node)
        {
            if (ecoSpace == null)
                throw new NullReferenceException("EcoSpace cannot be null!");
            if (node == null)
                throw new NullReferenceException("Node cannot be null!");

            InitializeComponent();

            undo = ecoSpace.GetEcoService<IUndoService>();

            if (undo == null)
                throw new NullReferenceException("UndoService must be registered in EcoSpace for NodeEditForm to work!");

            NodeVH.EcoSpace = ecoSpace;

            NodeVH.SetElementValue<Node>(node);
        }

        #region Image
        private void ChooseImageButton_Click(object sender, EventArgs e)
        {
            openImageDialog.FileName = Node.PathToImage;
            openImageDialog.ShowDialog();
        }

        private void openImageDialog_FileOk(object sender, CancelEventArgs e)
        {
            Node.PathToImage = PathUtility.MakePathLocal(openImageDialog.FileName, Locality.ExeFile); 
        } 
        #endregion

        #region Named states

        private void AddStateButton_Click(object sender, EventArgs e)
        {
            Node.NamedStates.Add(
                new NamedState(NodeVH.EcoSpace)
                {
                    Name = "State_" + Node.NamedStates.Count.ToString(),
                    Value = (NodeVH.Element.AsObject as Node).StateSet.BottomBound
                });
        }

        private void DelStateButton_Click(object sender, EventArgs e)
        {
            if (NamedStatesCMH.Element == null)
                return;

            (NamedStatesCMH.Element.AsObject as NamedState).AsIObject().Delete();
        }

        private void NamedStatesDGV_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            if (e.ColumnIndex == 2)
            {
                MessageBox.Show("Некорректное значение!", "Ошибка!",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                e.ThrowException = false;
            }
        }

        private void NamedStatesDGV_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 2)
            { 
                var value = (NamedStatesCMH.Element.AsObject as NamedState).Value;
                if ((value > Node.StateSet.UpperBound) || (value < Node.StateSet.BottomBound))
                {
                    MessageBox.Show("Значение должно быть внутри открезка " + Node.StateSet.ToString() + "!", 
                        "Ошибка!",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);

                    (NamedStatesCMH.Element.AsObject as NamedState).Value =
                        Node.StateSet.BottomBound;
                }
            }
        }

        #endregion

        #region Methods
        private void AddMethodButton_Click(object sender, EventArgs e)
        {
            Node.Methods.Add(
                new Method(NodeVH.EcoSpace)
                {
                    Name = "Method_" + Node.Methods.Count.ToString()
                });
        }

        private void DelMethodButton_Click(object sender, EventArgs e)
        {
            if (MethodsCMH.Element == null)
                return;

            (MethodsCMH.Element.AsObject as Method).AsIObject().Delete();
        }

        private void MethodsDGV_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (MethodsCMH.Element == null)
                return;

            var editform = new MethodEditForm(NodeVH.EcoSpace,
                MethodsCMH.Element.AsObject as Method);
            editform.ShowDialog();
        }
        #endregion

        #region Functions

        private void ChooseGotoButton_Click(object sender, EventArgs e)
        {
            var ocl = NodeVH.EcoSpace.GetEcoService<IOclService>();

            if (ocl == null)
            {
                MessageBox.Show("OclService is not registered yet!");
                return;
            }

            var functions = ocl.Evaluate("DomainModel.allInstances->first.FunctionLibrary.Functions").GetAsIList<Function>();

            Node.GotoFunction =
                ChooseOneForm<Function>.Choose("Выберите функицю абсолютного перехода", functions);
        }

        private void ChooseShiftButton_Click(object sender, EventArgs e)
        {
            var ocl = NodeVH.EcoSpace.GetEcoService<IOclService>();

            if (ocl == null)
            {
                MessageBox.Show("OclService is not registered yet!");
                return;
            }

            var functions = ocl.Evaluate("Function.allInstances").GetAsIList<Function>();

            Node.ShiftFunction =
                ChooseOneForm<Function>.Choose("Выберите функицю относительного перехода", functions);
        }

        #endregion

        #region Nodes
        private void NestedNodesButton_Click(object sender, EventArgs e)
        {
            var editform = new NodesEditForm(NodeVH.EcoSpace, NodeVH, "self.Nodes");

            editform.ShowDialog();
        }
        #endregion

        private void NodeEditForm_Load(object sender, EventArgs e)
        {
            undo.StartTransaction();
        }

        private void NodeEditForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (result)
                undo.CommitTransaction();
            else
                undo.RollbackTransaction();
        }

        private void OkButton_Click(object sender, EventArgs e)
        {
            result = true;
            Close();
        }

        private void CancelButton_Click(object sender, EventArgs e)
        {
            result = false;
            Close();
        }
    }
}
